﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;

namespace Drifting.Graphics.PhysicalObjects.Vehicles
{

    public class E92M3_Wheel : PhysicalObject
    {
        float angle = 0;
        float angle_front_axle = MathHelper.ToRadians(10);
        public E92M3_Wheel(Game1 game)
        {
            Body = game.Content.Load<Model>("models\\E92M3_wheel");
            Body_AbsoluteMatrix = new Matrix[Body.Bones.Count];
            Body.CopyAbsoluteBoneTransformsTo(Body_AbsoluteMatrix);

            body_scale = 0.01f;
            m_calibration = Matrix.CreateRotationY((float)Math.PI + 0.016f);
        }
        
        public void Draw_left_front(Matrix camera, Matrix projection, Matrix chassis_config, float steeringAngle)
        {
            foreach (ModelMesh mesh in Body.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.View = camera;
                    effect.Projection = projection;
                    effect.World =
                        Body_AbsoluteMatrix[mesh.ParentBone.Index] *
                        Matrix.CreateScale(body_scale) *
                        m_calibration *

                        Matrix.CreateRotationZ(-angle) *
                        Matrix.CreateRotationY(steeringAngle) *
                        Matrix.CreateRotationZ(angle_front_axle) *
                        Matrix.CreateTranslation(1.3805f, 0.33f, -(0.9105f - 0.173f))

                        * chassis_config;
                }
                mesh.Draw();
            }
            //angle += 0.05f;
        }

        public void Draw_right_front(Matrix camera, Matrix projection, Matrix chassis_config, float steeringAngle)
        {
            foreach (ModelMesh mesh in Body.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.View = camera;
                    effect.Projection = projection;
                    effect.World =
                        Body_AbsoluteMatrix[mesh.ParentBone.Index] *
                        Matrix.CreateScale(body_scale) *
                        m_calibration *

                        Matrix.CreateRotationZ(angle) *
                        Matrix.CreateRotationY(steeringAngle + (float)Math.PI) *
                        Matrix.CreateRotationZ(angle_front_axle) *
                        Matrix.CreateTranslation(1.3805f, 0.33f, (0.9105f - 0.173f))

                        * chassis_config;
                }
                mesh.Draw();
            }
            //angle += 0.05f;
        }

        public void Draw_left_rear(Matrix camera, Matrix projection, Matrix chassis_config)
        {
            foreach (ModelMesh mesh in Body.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.View = camera;
                    effect.Projection = projection;
                    effect.World =
                        Body_AbsoluteMatrix[mesh.ParentBone.Index] *
                        Matrix.CreateScale(body_scale) *
                        m_calibration *

                        Matrix.CreateRotationZ(-angle) *
                        Matrix.CreateTranslation(-1.3805f, 0.33f, -(0.9105f - 0.173f))

                        * chassis_config;
                }
                mesh.Draw();
            }
            //angle += 0.05f;
        }

        public void Draw_right_rear(Matrix camera, Matrix projection, Matrix chassis_config)
        {
            foreach (ModelMesh mesh in Body.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.View = camera;
                    effect.Projection = projection;
                    effect.World =
                        Body_AbsoluteMatrix[mesh.ParentBone.Index] *
                        Matrix.CreateScale(body_scale) *
                        m_calibration *

                        Matrix.CreateRotationZ(angle) *
                        Matrix.CreateRotationY((float)Math.PI) *
                        Matrix.CreateTranslation(-1.3805f, 0.33f, (0.9105f - 0.173f))

                        * chassis_config;
                }
                mesh.Draw();
            }
            //angle += 0.05f;
        }

        override public void Draw(Matrix camera, Matrix projection)
        {
            throw new InvalidOperationException();
        }
    }

    public class E92M3_Disk : PhysicalObject
    {
        public E92M3_Disk(Game1 game)
        {
            Body = game.Content.Load<Model>("models\\E92M3_disk");
            Body_AbsoluteMatrix = new Matrix[Body.Bones.Count];
            Body.CopyAbsoluteBoneTransformsTo(Body_AbsoluteMatrix);

            body_scale = 0.01f;
            m_calibration = Matrix.CreateRotationY((float)Math.PI + 0.016f) ;
        }

        public void Draw_left_front(Matrix camera, Matrix projection, Matrix chassis_config, float steeringAngle)
        {
            foreach (ModelMesh mesh in Body.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.View = camera;
                    effect.Projection = projection;
                    effect.World =
                        Body_AbsoluteMatrix[mesh.ParentBone.Index] *
                        Matrix.CreateScale(body_scale) *
                        m_calibration *

                        Matrix.CreateRotationY(steeringAngle) *
                        Matrix.CreateTranslation(1.3805f, 0.33f, -(0.9105f - 0.173f))

                        * chassis_config;
                }
                mesh.Draw();
            }
        }

        public void Draw_right_front(Matrix camera, Matrix projection, Matrix chassis_config, float steeringAngle)
        {
            foreach (ModelMesh mesh in Body.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.View = camera;
                    effect.Projection = projection;
                    effect.World =
                        Body_AbsoluteMatrix[mesh.ParentBone.Index] *
                        Matrix.CreateScale(body_scale, body_scale, -body_scale) *
                        m_calibration *

                        Matrix.CreateRotationY(steeringAngle) *
                        Matrix.CreateTranslation(1.3805f, 0.33f, (0.9105f - 0.173f))

                        * chassis_config;
                }
                mesh.Draw();
            }
        }

    }

    public class E92M3 : PhysicalObject
    {
        E92M3_Wheel wheel;
        E92M3_Disk disk;

        public E92M3(Game1 game)
        {
            Body = game.Content.Load<Model>("models\\E92M3_body");
            Body_AbsoluteMatrix = new Matrix[Body.Bones.Count];
            Body.CopyAbsoluteBoneTransformsTo(Body_AbsoluteMatrix);

            body_scale = 0.01f;
            m_calibration = Matrix.CreateRotationY((float)Math.PI) * Matrix.CreateTranslation(0.036f, 0, 0);

            wheel = new E92M3_Wheel(game);
            disk = new E92M3_Disk(game);
        }
        
        override public void Draw(Matrix camera, Matrix projection)
        {
            throw new InvalidOperationException();
        }
        
        public void Draw(Matrix camera, Matrix projection, float q_x, float q_y, float q_t, float steeringAngle)
        {
            Matrix config = Matrix.CreateRotationY(q_t) *
                            Matrix.CreateTranslation(q_x, 0, -q_y);

            foreach (ModelMesh mesh in Body.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.View = camera;
                    effect.Projection = projection;
                    effect.World =

                        Body_AbsoluteMatrix[mesh.ParentBone.Index] *

                        Matrix.CreateScale(body_scale) *

                        m_calibration *

                        config;
                }
                mesh.Draw();
            }

            disk.Draw_left_front(camera, projection, config, steeringAngle);
            disk.Draw_right_front(camera, projection, config, steeringAngle);
            wheel.Draw_left_front(camera, projection, config, steeringAngle);
            wheel.Draw_right_front(camera, projection, config, steeringAngle);
            wheel.Draw_left_rear(camera, projection, config);
            wheel.Draw_right_rear(camera, projection, config);
        }
    }
}
